package cn.iocoder.yudao.module.product.category.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.NumberUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.product.category.dal.dataobject.ProductCategoryDO;
import cn.iocoder.yudao.module.product.category.vo.AppProductCategoryListReqVO;
import cn.iocoder.yudao.module.product.category.vo.ProductCategoryListReqVO;
import cn.iocoder.yudao.module.product.category.vo.ProductCategoryPageReqVO;
import cn.iocoder.yudao.module.product.category.vo.ProductCategorySaveReqVO;
import jakarta.annotation.Nullable;
import jakarta.validation.Valid;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import static cn.iocoder.yudao.module.product.category.dal.dataobject.ProductCategoryDO.CATEGORY_TOP_LEVEL_ROOT;

/**
 * 产品分类 Service 实现类
 *
 * @author 芋道源码
 */
public interface ProductCategoryService {

    /**
     * 创建产品分类
     *
     * @param createReqVO 创建信息
     * @return 编号
     */
    Long createCategory(@Valid ProductCategorySaveReqVO createReqVO);

    /**
     * 更新产品分类
     *
     * @param updateReqVO 更新信息
     */
    void updateCategory(@Valid ProductCategorySaveReqVO updateReqVO);

    /**
     * 删除产品分类
     *
     * @param id 编号
     */
    void deleteCategory(Long id);

    /**
     * 获得产品分类
     *
     * @param id 编号
     * @return 产品分类
     */
    ProductCategoryDO getCategory(Long id);

    /**
     * 校验产品分类
     *
     * @param id 分类编号
     */
    default void validateCategory(Long id) {
        validateCategory(id, CATEGORY_TOP_LEVEL_ROOT);
    }

    /**
     * 校验产品分类
     *
     * @param id 分类编号
     */
    void validateCategory(Long id, Integer level);

    /**
     * 获得产品分类的层级
     *
     * @param id 编号
     * @return 产品分类的层级
     */
    Integer getCategoryLevel(Long id);

    /**
     * 获得产品分类列表
     *
     * @param listReqVO 查询条件
     * @return 产品分类列表
     */
    List<ProductCategoryDO> getCategoryList(ProductCategoryListReqVO listReqVO);

    /**
     * 获得产品分类列表
     */
    List<ProductCategoryDO> getAllCategoryList();

    /**
     * 获得产品分类列表
     *
     * @param shopId 店铺编号
     * @param parentIds 上级编号
     * @return 产品分类列表
     */
    List<ProductCategoryDO> getEnableCategoryList(Long shopId, Set<Long> parentIds);

    /**
     * 获得开启状态的产品分类列表，指定编号
     *
     * @param ids 产品分类编号数组
     * @return 产品分类列表
     */
    List<ProductCategoryDO> getEnableCategoryList(Set<Long> ids);

    /**
     * 校验产品分类是否有效。如下情况，视为无效：
     * 1. 产品分类编号不存在
     * 2. 产品分类被禁用
     *
     * @param ids 产品分类编号数组
     */
    void validateCategoryList(Set<Long> ids);

    /**
     * 获得类目分页
     */
    PageResult<ProductCategoryDO> getCategoryPage(ProductCategoryPageReqVO reqVO);

    /**
     * 获得指定类目的所有子类目
     *
     * @param shopId 店铺编号
     * @param parentIds 类目编号
     * @param status    启用/关闭
     * @return 子类目列表
     */
    List<ProductCategoryDO> getDescendentCategoryList(@Nullable Long shopId, Set<Long> parentIds, Integer status);

    /**
     * 获得所有子类目，从缓存中
     *
     * @param parentId 父类目编号
     * @param status   启用/关闭
     * @return 子类目列表
     */
    Set<Long> getDescendentCategoryIdsFromCache(Long parentId, Integer status);

    /**
     * 获得开启状态的产品分类列表
     *
     * @param listReqVO 查询条件
     * @return 产品分类列表
     */
    default List<ProductCategoryDO> getEnableCategoryList(AppProductCategoryListReqVO listReqVO) {
        HashSet<Long> parentIds = new HashSet<>();
        if (listReqVO.getParentId() != null) {
            parentIds.add(listReqVO.getParentId());
        }
        if (CollUtil.isNotEmpty(listReqVO.getParentIds())) {
            parentIds.addAll(listReqVO.getParentIds());
        }
        return getEnableCategoryList(listReqVO.getShopId(), parentIds);
    }

    /**
     * 获得开启状态的产品分类列表
     *
     * @param listReqVO 查询条件
     * @return 产品分类列表
     */
    default List<ProductCategoryDO> getEnableDescendentCategoryList(AppProductCategoryListReqVO listReqVO) {
        HashSet<Long> parentIds = new HashSet<>();
        if (listReqVO.getParentId() != null) {
            parentIds.add(listReqVO.getParentId());
        }
        if (CollUtil.isNotEmpty(listReqVO.getParentIds())) {
            parentIds.addAll(listReqVO.getParentIds());
        }
        return getDescendentCategoryList(NumberUtil.nullToZero(listReqVO.getShopId()), parentIds, CommonStatusEnum.ENABLE.getStatus());
    }

}
